package com.baihan.angus.app.game.basic.utils.net;


import android.text.TextUtils;

import com.baihan.angus.app.game.basic.BaseApplication;
import com.baihan.angus.app.game.basic.utils.AppUtil;
import com.baihan.angus.app.game.basic.utils.Loog;
import com.baihan.angus.app.game.basic.utils.net.cookie.CookieManager;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Retrofit 帮助类
 */
public class RetrofitHelper {
    private static OkHttpClient mOkHttpClient;

    static {
        initOkHttpClient();
    }

    private static Map<String, Object> mServerMap = new HashMap<>();


    /**
     * 创建api
     */
    public static <T> T createApi(Class<T> clazz) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(NetConstant.BASE_HOST)
                .client(mOkHttpClient)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return retrofit.create(clazz);
    }

    /**
     * 创建api
     * 含baseUrl的重载函数
     */
    public static <T> T createApi(Class<T> clazz, String baseUrl) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(mOkHttpClient)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return retrofit.create(clazz);
    }

    /**
     * 创建api
     */
    public static <T> T createApiWithLongTime(Class<T> clazz, String baseUrl) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(mOkHttpClient.newBuilder().connectTimeout(30, TimeUnit.SECONDS)
                        .writeTimeout(30, TimeUnit.SECONDS)
                        .readTimeout(30, TimeUnit.SECONDS).build())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return retrofit.create(clazz);
    }

    /**
     * 一些特殊Api需要自定义一些配置用
     */
    public static Retrofit getBaseConfigRetrofit() {
        Retrofit retrofit = new Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return retrofit;
    }

    /**
     * 用于自定义配置 mOkHttpClient
     *
     * @return
     */
    public static OkHttpClient getOkHttpClient() {
        if (mOkHttpClient == null) initOkHttpClient();
        return mOkHttpClient;
    }

    /**
     * 初始化OKHttpClient,设置超时时间,设置打印日志
     */
    private static void initOkHttpClient() {
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, null);
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        if (mOkHttpClient == null) {
            synchronized (RetrofitHelper.class) {
                if (mOkHttpClient == null) {
                    mOkHttpClient = new OkHttpClient.Builder()
                            .addInterceptor(interceptor)
                            .retryOnConnectionFailure(true)
                            .connectTimeout(30, TimeUnit.SECONDS)
                            .writeTimeout(30, TimeUnit.SECONDS)
                            .readTimeout(60, TimeUnit.SECONDS)
                            .addInterceptor(new TokenAndConfigInterceptor())
                            .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                            .cookieJar(new CookieManager(BaseApplication.getApplication()))
                            .build();
                }
            }
        }
    }


    /**
     * 添加token与配置请求拦截器
     */
    private static class TokenAndConfigInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {

            Request originalRequest = chain.request();
            RequestBody rb = originalRequest.body();

            String nonce = new BigDecimal(100000 + Math.random() * (900000)).setScale(0, RoundingMode.HALF_DOWN).toPlainString();
            String timestamp = String.valueOf(System.currentTimeMillis());
            String deviceNo = BaseApplication.getApplication().getDeviceNo();
            if (TextUtils.isEmpty(deviceNo)) {
                //随机一个伪设备号出来
                deviceNo = UUID.randomUUID().toString();
            }
            StringBuffer signBuffer = new StringBuffer();
            signBuffer.append(NetConstant.HTTP_MIMI)//key
                    .append("0")//设备
                    .append(deviceNo)//设备
                    .append(nonce)//随机六位数
                    .append(timestamp);//时间戳

            String b = "--";
            if (rb != null && rb.contentLength() > 0 && rb.contentType().equals(MediaType.parse("application/json; charset=UTF-8"))) {
                Buffer buffer = new Buffer();
                rb.writeTo(buffer);
                String body = buffer.readString(Charset.forName("UTF-8"));
                b = body;
                signBuffer.append(b);
            }
            String sign = AppUtil.getMD5Str(signBuffer.toString());


            Loog.d("RetrofitHelper", "signBuffer = " + signBuffer.toString() +
                    "\n body = " + b +
                    "\n sign = " + sign +
                    "\n token = " + BaseApplication.getApplication().getAppServerToken() +
                    "\n deviceNo = " + deviceNo
            );

            Request requestWithToken = originalRequest.newBuilder()
                    .header("device", "0")
                    .header("deviceNo", deviceNo)
                    .header("nonce", nonce)
                    .header("timestamp", timestamp)
                    .header("sign", sign)
                    .header("token", BaseApplication.getApplication().getAppServerToken())
                    .build();

            return chain.proceed(requestWithToken);
        }
    }


}
